﻿
Imports System.IO
Imports std

'except for existing vector functions, also take care to transform from any to bytes, or bytes to any
'uses ToString and encoding.utf8.GetBytes, and encoding.utf8.GetString
'meanwhile, has export and import functions
'to export nettransData to bytes, and imports bytes from network to nettransData

Public Class nettransData
    Inherits vector(Of bytes)
    Implements IDisplay

    Public Const displayRange As UInt32 = 128
    Public ReadOnly sizeofInt64 As Int32 = sizeof(Of Int64)()

    Public Shared Function emptyInstance() As nettransData
        Static rtn As nettransData = New nettransData()
        rtn.size() = 0
        Return rtn
    End Function

    Public Function export(ByRef buff() As Byte, ByVal start As Int64, ByRef size As Int64) As Boolean
        size = 0
        Dim i As Int64
        For i = 0 To Me.size() - 1
            If data(i) Is Nothing Then
                size += sizeofInt64
            Else
                size += data(i).size + sizeofInt64
            End If
        Next
        If buff Is Nothing Then
            ReDim buff(start + size - 1)
        ElseIf buff.Length < start + size Then
            ReDim Preserve buff(start + size - 1)
        End If

        Dim mem As MemoryStream = Nothing
        mem = New MemoryStream(buff, start, size)
        Dim writer As BinaryWriter = Nothing
        writer = New BinaryWriter(mem)
        assert(Not writer Is Nothing, "cannot create BinaryWriter and MemoryStream on buff")
        For i = 0 To Me.size() - 1
            If data(i) Is Nothing Then
                writer.Write(Convert.ToInt64(0))
            Else
                writer.Write(data(i).size())
                If Not +(data(i)) Is Nothing Then
                    writer.Write(+data(i))
                End If
            End If
        Next

        assert(writer.BaseStream.Position = size, "writer.BaseStream.Position <> size")
        closeBinaryWriter(writer)
        closestream(mem)

        Return True
    End Function

    Public Function export(ByRef buff() As Byte, ByRef size As Int64) As Boolean
        Return export(buff, 0, size)
    End Function

    Public Function export(ByRef buff() As Byte) As Boolean
        Dim size As Int64 = 0
        Return export(buff, size)
    End Function

    Public Function import(ByVal buff() As Byte, ByVal start As Int64, ByVal size As Int64) As Boolean
        If buff Is Nothing OrElse start + size > Convert.ToInt64(buff.Length) Then
            Return False
        Else
            Dim mem As MemoryStream = Nothing
            mem = New MemoryStream(buff, start, size)
            Dim reader As BinaryReader = Nothing
            reader = New BinaryReader(mem)
            assert(Not reader Is Nothing, "cannot create BinaryReader and MemoryStream on buff")

            While mem.Position() < mem.Length() AndAlso binaryReaderHelper.readInt64(reader, size)
                insert(reader.ReadBytes(size))
            End While

            closeBinaryReader(reader)
            closestream(mem)

            Return True
        End If
    End Function

    Public Function import(ByVal buff() As Byte) As Boolean
        If buff Is Nothing Then
            Return False
        End If
        Return import(buff, 0, buff.Length)
    End Function

    Public Function fieldCount() As Int64
        Return size()
    End Function

    Public Sub New()
        MyBase.New()
    End Sub

    Public Sub New(ByVal value As nettransData)
        MyBase.New()
        push_back(value.data)
    End Sub

    Public Function display(Optional ByVal length As Long = 64) As String Implements IDisplay.display
        Dim rtn As String = Nothing
        Dim i As Int64
        Dim buff As bytes = Nothing
        Dim temp As String = Nothing
        Dim singleRange As Int64
        If size() < 2 Then
            singleRange = displayRange
        Else
            singleRange = displayRange \ size()
        End If
        rtn = "{fieldCount}" + size().ToString
        For i = 0 To min(size() - 1, convertor.cast(Of Int64)(displayRange))
            buff = data(i)
            escape(System.Text.Encoding.UTF8.GetString(+buff, 0, min(buff.size, singleRange)), temp)
            rtn += character.fullStop
            rtn += character.fullStop
            rtn += character.fullStop
            rtn += character.sheffer
            rtn += character.leftBrace + buff.size.ToString + character.rightBrace + temp
        Next
        Return rtn
    End Function

    Public Overloads Function take(ByVal index As Int64) As bytes
        Dim rtn As bytes = Nothing
        If MyBase.take(index, rtn) Then
            Return rtn
        Else
            Return Nothing
        End If
    End Function

    Public Overloads Function take(ByVal index As Int64, ByRef value As bytes) As Boolean
        Return MyBase.take(index, value)
    End Function

    Public Overloads Function take(Of T)(ByVal index As Int64, ByRef value As T) As Boolean
        Dim field As bytes = Nothing
        field = take(index)
        If field Is Nothing Then
            value = Nothing
            Return False
        Else
            Dim str As String
            If Not +field Is Nothing Then
                str = encoding.utf8.GetString(+field, 0, field.size)
                Return convertor.cast(Of T)(str, value)
            Else
                Return False
            End If
        End If
    End Function

    Public Overloads Function take(Of valueT)(ByVal index As Int64) As valueT
        Dim temp As valueT
        If take(index, temp) Then
            Return temp
        Else
            Return Nothing
        End If
    End Function

    Public Overloads Function push_back(ByVal v As bytes) As Boolean
        Return MyBase.push_back(v)
    End Function

    Public Overloads Function push_back(ByVal v() As Byte) As Boolean
        Return MyBase.push_back(v)
    End Function

    Public Overloads Function push_back(Of valueT)(ByVal value As valueT) As Boolean
        Dim internal As bytes = New bytes(encoding.utf8.GetBytes(Convert.ToString(value)))
        Return MyBase.push_back(internal)
    End Function

    Public Overloads Function insert(ByVal v As bytes) As Boolean
        Return push_back(v)
    End Function

    Public Overloads Function insert(ByVal v() As Byte) As Boolean
        Return push_back(v)
    End Function

    Public Overloads Function insert(Of valueT)(ByVal value As valueT) As Boolean
        Return push_back(value)
    End Function

    Public Overrides Function Clone() As Object
        Dim rtn As nettransData = Nothing
        rtn = New nettransData(Me)

        Return rtn
    End Function

    Public Shared Sub unittest()
        Dim testsize As Int32 = 100000
        Dim d As nettransData = Nothing
        d = New nettransData
        Dim i As Int32
        perfCheckPoint(, "begin", True)
        For i = 0 To testsize
            d.insert("abc")
        Next
        perfCheckPoint(, "finish insert " + Convert.ToString(testsize + 1) + " 'abc' to d", True)
        Dim buff() As Byte = Nothing
        Dim size As Int32
        d.export(buff, size)
        perfCheckPoint(, "finish export from d", True)
        d.clear()
        perfCheckPoint(, "finish d.clear()", True)
        d.import(buff)
        perfCheckPoint(, "finish d.import(buff)", True)
        assert(testsize + 1 = d.fieldCount, "testsize+1<>d.fieldCount")
        For i = 0 To testsize
            assert(d.take(Of String)(i) = "abc", "d.take(Of String)(i) <> 'abc'")
        Next
        perfCheckPoint(, "finish d.take", True)
    End Sub
End Class
